// Copyright 2006 PR1ME. All Rights Reserved.

/**
 * Represents the user's current command state.
 */
public class CommandState {

  private class BrowseCommand implements Command {
    public boolean accept(Corpus corpus, String[] args) {
      if (args.length > 1) {
        System.out.println("Inappropriate request");
        return false;
      }

      if (args.length == 0) {
        cluster = corpus.getTopCluster();
      } else {
        if (cluster == null) {
          System.out.println("Inappropriate request; no previous browse is active");
          return false;
        }

        SuperCluster superCluster = cluster.isSuperCluster();
        if (superCluster == null) {
          System.out.println("Inappropriate request; previous browse is a leaf node");
          return false;
        }

        int index;
        try {
          index = Integer.parseInt(args[0]);
        } catch (NumberFormatException e) {
          System.out.println("Argument must be numeric");
          return false;
        }

        Cluster tmp = superCluster.getSubcluster(index);
        if (tmp == null) {
          System.out.println("Inappropriate request; index out of range");
          return false;
        }

        cluster = tmp;
      }

      String[] items = cluster.getItems();
      boolean isSuper = cluster.isSuperCluster() != null;
      for (int i = 0; i < items.length; ++i) {
        if (isSuper) {
          System.out.print(i + ": ");
        }
        System.out.println(items[i]);
      }
      return true;
    }

    public String getName() {
      return "BROWSE";
    }
  }

  private class DisplayCommand implements Command {
    public boolean accept(Corpus corpus, String[] args) {
      if (args.length != 1) {
        System.out.println("Inappropriate request");
        return false;
      }
      CorpusFile file = corpus.getCorpusFile(args[0]);
      if (file == null) {
        System.out.println("No such corpus file");
        return false;
      }
      String text = file.getContents();
      System.out.println(text);
      return true;
    }

    public String getName() {
      return "DISPLAY";
    }
  }

  private class IndexCommand implements Command {
    public boolean accept(Corpus corpus, String[] args) {
      if (args.length != 0) {
        System.out.println("Inappropriate request");
        return false;
      }
      System.out.println(corpus.getIndexText());
      return true;
    }

    public String getName() {
      return "INDEX";
    }
  }

  private class QueryCommand implements Command {
    public boolean accept(Corpus corpus, String[] args) {
      if (args.length == 0) {
        System.out.println("Inappropriate request");
        return false;
      }
      CorpusFile[] results = corpus.query(args);
      if (results.length == 0) {
        System.out.println("No results");
      } else {
        for (int i = 0; i < results.length; ++i) {
          System.out.println(results[i].getFilePath());
        }
      }
      return true;
    }

    public String getName() {
      return "QUERY";
    }
  }

  private class QuitCommand implements Command {
    public boolean accept(Corpus corpus, String[] args) {
      if (args.length != 0) {
        System.out.println("Inappropriate request");
        return false;
      }
      System.exit(0);
      return true;
    }

    public String getName() {
      return "QUIT";
    }
  }

  private class SimilarToCommand implements Command {
    public boolean accept(Corpus corpus, String[] args) {
      if (args.length != 1) {
        System.out.println("Inappropriate request");
        return false;
      }
      CorpusFile base = corpus.getCorpusFile(args[0]);
      if (base == null) {
        System.out.println("No such corpus file");
        return false;
      }
      CorpusFile[] results = corpus.similarTo(base);
      if (results.length == 0) {
        System.out.println("No results");
      } else {
        for (int i = 0; i < results.length; ++i) {
          System.out.println(results[i].getFilePath());
        }
      }
      return true;
    }

    public String getName() {
      return "SIMILARTO";
    }
  }

  private class StatsCommand implements Command {
    public boolean accept(Corpus corpus, String[] args) {
      if (args.length != 0) {
        System.out.println("Inappropriate request");
        return false;
      }
      System.out.println(corpus.getStatsText());
      return true;
    }

    public String getName() {
      return "STATS";
    }
  }

  public CommandState(Corpus corpus) {
    this.corpus = corpus;
  }

  public void process(String cmdName, String[] cmdArgs) {
    for (int i = 0; i < COMMAND.length; ++i) {
      Command cmd = COMMAND[i];
      if (cmd.getName().equalsIgnoreCase(cmdName)) {
        cmd.accept(corpus, cmdArgs);
        return;
      }
    }
    System.out.println("Unknown command");
  }

  public Cluster cluster = null;

  private final Command[] COMMAND = new Command[] {
      new StatsCommand(), new IndexCommand(), new QueryCommand(),
      new SimilarToCommand(), new BrowseCommand(), new DisplayCommand(),
      new QuitCommand()};

  private final Corpus corpus;

}
